(ns web
  (:require [clojure.contrib.json :as json])
  (:require [clojure.contrib.seq-utils :as seq])
  (:require [clojure.contrib.str-utils2 :as str])
  (:import java.net.URLDecoder)
  (:import java.net.URLEncoder)
  (:import (java.io File))
  (:use compojure.core, ring.adapter.jetty)
  (:use hiccup.core hiccup.page-helpers)
  (:require [compojure.route :as route])
)

(import '(java.util.concurrent BlockingQueue LinkedBlockingQueue TimeUnit))

(defn url-decode [param]
  (URLDecoder/decode param "iso-8859-1"))

(defn zip-str [coll del]
  (reduce #(format "%s%s%s" %1 del %2) coll))

(defn spacing [coll]
  (zip-str coll " "))

(defn zip-a [coll del]
  (reduce #(format "%s%s%s" (html %1) del (html %2)) coll))

(defn spacing-a [coll]
  (when (> (count coll) 0)
    (zip-a coll "&nbsp;&nbsp;")))

(defn newline-a [coll]
  (zip-a coll "<br />"))

(defn template [name]
  (slurp (str global/web-folder "/template/" name ".html")))

(defn js [script]
  (include-js (str "/js/" script ".js")))

(defn load-static-file []
  (route/files "/" {:root global/web-folder}))

(defn header-js []
     (html (include-css "/css/searchlight.css")
	   (include-css "/css/global.css")
	   (js "jquery-1.4.2-min")
	   (js "jquery.tmpl")
	   (js "jquery.json-2.2.min")
	   (js "jquery.searchlight")
	   (js "notification")
	   (js "header")))

; {:link "/covers" :name "Covers"}

(map #(link-to (:link %) (:name %)) [{:link "/movies" :name "Movies"}
				     {:link "/dvd" :name "Play DVD"}])

(defn top-header []
  (str (html (spacing-a (vector (link-to "/movies" "Movies") (link-to {:class "dvd-link"} "/dvd" "Play DVD"))) 
	     "<span id=\"search-container\">Search: <input id=\"search\" autocomplete=\"off\"></span>"
	     )))

(defn path-ok [path]
  (some #(. path startsWith %) global/movie-folders))
  
(defn get-files [path]
  (cond (= path "")
	(seq/flatten (map #(movie/list-folder %) global/movie-folders))
	:else
	(cond (path-ok path)
	      (movie/list-folder path)
	      :else '())))

(defn movie-line [mov]
  (cond (:modified mov)
	(html [:tr [:td (link-to {:class "movie-link"} (str "/movies/" (URLEncoder/encode (:path mov))) (:name mov))]])
	:else
	(html [:tr [:td (link-to (str "/movies/" (URLEncoder/encode (:path mov))) (:name mov))]])))

(defn internet-movie-line [mov]
  (let [info (@movie/movie-infos (:path mov))
	imdb-info #(link-to (:imdb-url %) (str "imdb: " (:imdb-rating %)))
	rotten-info #(link-to (:rotten-tomatoes-url %) (str "rotten tomatoes: " (:rotten-tomatoes-rating %)))
	info-html (cond info
			(html [:br]
			(cond (:imdb-rating info)
			      (html
			       (imdb-info info)
			       "&nbsp;&nbsp;&nbsp"))
			(cond (:rotten-tomatoes-rating info)
			      (html
			       (rotten-info info)
			       "&nbsp;&nbsp;&nbsp"))
			(cond (:year info)
			      (str "Year: " (:year info)))
			[:br][:br])
			:else "")]
    (cond (:modified mov)
	  (html [:tr
		 [:td {:width 110}
		  (cond (:image info)
			[:img {:width 100 :height 146 :src (:image info)}])]
		 [:td 
		      (link-to {:class "movie-link"} (str "/movies/" (URLEncoder/encode (:path mov))) (:name mov))
		      info-html
		      ]]))
	   :else
	   (html [:tr
		  [:td {:width 110}
		   (cond (:image info)
			 [:img {:class "cover" :src (:image info)}])]
		  [:td {:style "vertical-align:top;"}
		   (link-to (str "/movies/" (URLEncoder/encode (:path mov))) (movie/fix-name (:name mov)))
		   info-html
		   ]])))

(defn one-up [path]
  (. path substring 0 (. path lastIndexOf "/")))

(defn movies [path]
  (let [files (sort (common/simple-cmp :name) (get-files path))]
    (html4
     [:head 
      [:title "Movies"]
      (header-js)
      (js "movie")]
     [:body 
      (top-header)
      [:h1 "Movies"]
      [:a {"href" "" :class "reload"} "reload"]"&nbsp;&nbsp;&nbsp;"
      [:a {"href" path :class "update-internet-info"} "update movie info"]
      [:br][:br]
      (when (not= path "")
	(let [one-dir-up (one-up path)]
	  (html
	   (cond (some #{(str one-dir-up "/")} global/movie-folders)
		 (link-to "/movies/" "back")
		 :else
		 (link-to (str "/movies/" one-dir-up) "back"))
	   [:br]
	   [:br])))
      [:table
       (cond (movie/is-internet-info-folder path)
	     (map internet-movie-line files)
	     :else
	     (map movie-line files))]
      ])))

(defn play-dvd []
  (println (str (global/playback-commands "dvd") " dvdnav://"))
  (common/run-simple-command-with-output common/cmdout (vector "/bin/bash" "-c" (str (global/playback-commands "dvd") " dvdnav://")))
  "")

(defn icontains? [s substring]
  (str/contains? (. s toLowerCase) (. substring toLowerCase)))

(defn search [search]
  "")

(defn play-movie [path]
  (println (str "playing:" (str (global/playback-commands (movie/extension path)) " '" path "'")))
  (movie/update-last-watched path)
  (common/run-simple-command-with-output common/cmdout (vector "/bin/bash" "-c" (str (global/playback-commands (movie/extension path)) " '" path "'"))))

(defn handle-command [cmd params]
  (cond (= cmd "play-movie")
	(play-movie (url-decode (params "name")))
	(= cmd "play-dvd")
	(play-dvd)
	(= cmd "reload")
	(movie/read-files))
	(= cmd "update-internet-info")
	(movie/update-movie-info (url-decode (params "name")))
  "")

(defroutes my-routes
  (POST "/control" {params :params}
    (handle-command (params "command") params))
  (GET ["/movies/:path" :path #".*"] [path]
    (movies path))
  (GET "/" []
    (movies ""))
  (GET "/movies" []
    (movies ""))
  (GET "/search" {params :params}
    (search (params "q")))
  (GET ["/js/:filename" :filename #".*"] [filename]
    (load-static-file))
  (GET ["/css/:filename" :filename #".*"] [filename]
    (load-static-file))
  (GET ["/img/:filename" :filename #".*"] [filename]
    (load-static-file))
  (route/not-found (html [:h1 "Page not found!"])))

(run-jetty (var my-routes) {:port 6667})
